<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width= , initial-scale=1.0" />
    <title>3D transform</title>
    <style>
      body {
        perspective: 800px;
      }
      .wrapper {
        width: 300px;
        height: 300px;
        /* border: 1px solid #000; */
        position: relative;
        margin: 100px auto;
        transform-style: preserve-3d;
        transition: transform 2s;
      }
      .wrapper .face {
        width: 200px;
        height: 200px;
        position: absolute;
        top: 50%;
        margin-top: -100px;
        left: 50%;
        margin-left: -100px;
        text-align: center;
        line-height: 200px;
        font-size: 150px;
      }
      .face:nth-child(1) {
        background-color: aqua;
        transform: translateZ(100px);
      }
      .face:nth-child(2) {
        background-color: salmon;
        transform: translateZ(-100px);
      }
      .face:nth-child(3) {
        background-color: skyblue;
        transform: rotateY(90deg) translateZ(100px);
      }
      .face:nth-child(4) {
        background-color: palevioletred;
        transform: rotateY(-90deg) translateZ(100px);
      }
      .face:nth-child(5) {
        background-color: springgreen;
        transform: rotateX(90deg) translateZ(100px);
      }
      .face:nth-child(6) {
        background-color: crimson;
        transform: rotateX(-90deg) translateZ(100px);
      }
    </style>
  </head>
  <body>
    <div class="wrapper" id="wrapper">
      <div class="face">1</div>
      <div class="face">2</div>
      <div class="face">3</div>
      <div class="face">4</div>
      <div class="face">5</div>
      <div class="face">6</div>
    </div>

    <script>
      const wrapper = document.getElementById('wrapper')
      let isMouseDown = false
      let touchLastX = null
      let touchLastY = null
      let xDeg = 0
      let yDeg = 0

      document.addEventListener('mousedown', () => {
        isMouseDown = true
      })
      document.addEventListener('mouseup', () => {
        isMouseDown = false
      })
      document.addEventListener('mousemove', (e) => {
        if (isMouseDown) {
          requestAnimationFrame(() => {
            xDeg += e.movementX
            yDeg += e.movementY
            wrapper.style.transform = `rotateX(${-yDeg}deg) rotateY(${xDeg}deg)`
          })
        }
      })

      document.addEventListener('touchstart', (e) => {
        isMouseDown = true
        touchLastX = e.touches[0].clientX
        touchLastY = e.touches[0].clientY
      })
      document.addEventListener('touchend', () => {
        isMouseDown = false
        touchLastX = null
        touchLastY = null
      })
      document.addEventListener(
        'touchmove',
        (e) => {
          e.preventDefault()
          if (isMouseDown) {
            xDeg += e.touches[0].clientX - touchLastX
            yDeg += e.touches[0].clientY - touchLastY
            touchLastX = e.touches[0].clientX
            touchLastY = e.touches[0].clientY
            requestAnimationFrame(() => {
              wrapper.style.transform = `rotateX(${-yDeg}deg) rotateY(${xDeg}deg)`
            })
          }
        },
        { passive: false },
      )
    </script>
  </body>
</html>
